package com.kirk.crawler.ui;

import com.kirk.crawler.constant.SystemConstants;
import com.kirk.crawler.constant.UserConstants;
import com.kirk.crawler.core.cache.UserCacheManager;
import com.kirk.crawler.core.context.CrawlerToolContextData;
import com.kirk.crawler.ui.widget.JFilterTextField;
import com.kirk.crawler.ui.widget.UrlLabel;
import com.kirk.crawler.utils.ImageManager;
import com.kirk.crawler.webService.utils.WebServiceUtil;
import com.sun.awt.AWTUtilities;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

/**
 *  <p> CrawlerToolLogin.java </p>
 *
 * @Author      kirkliu
 * @Date        2020-08-29 22:32
 * @version     1.0.0
 * @Description 登陆页面视图
 */
public abstract class CrawlerToolLogin extends JFrame {

    protected static final Log logger = LogFactory.getLog(CrawlerToolLogin.class);

    /** 登陆窗口宽 */
    private final static int width = 332;
    /** 登陆窗口高 */
    private final static int height = 344;

    /**
     * 组件定义
     */
    // logo标签的定义
    private JLabel logoLabel;
    // 登陆按钮定义
    private JButton btnLogin;
    // 输入内容的容器定义
    private JPanel inputPane;
    // 顶部容器定义
    private JPanel topPane;
    //错误提示标签的定义
    protected JLabel errorLabel;
    // 网络设置按钮定义
    private JLabel netSetLabel;
    // 退出按钮定义
    private JLabel exitLabel;
    // 自定义用户名输入域定义
    protected JFilterTextField userNameTextField;
    // 密码输入域定义
    protected JTextField passwordTextField;
    // 是否记住我单选框定义
    protected JCheckBox rememberMe;

    /**
     * 监听对象的定义
     */
    // 鼠标监听事件定义
    private MouseAdapter moveWindowListener;

    /**
     * 资源对象的定义
     */
    // logo图标资源定义
    private ImageIcon logoIcon;
    // logo点亮图标资源定义
    private ImageIcon logoRoverIcon;
    // logo图标资源定义
    private ImageIcon buttonIcon;
    // 登陆按钮点亮图标
    private ImageIcon buttonRoverIcon;
    // 登陆按钮按下图标
    private ImageIcon buttonPressedIcon;

    /*
     * 用户相关属性
     */

    /** 用户缓存管理类 */
    protected UserCacheManager userCacheManager = UserCacheManager.getInstance();
    /** 柜员号集合 */
    protected List<Object> userIdList;
    /** 最后一次登录用户ID */
    protected String lastUserId = "";


    // 默认构造方法
    public CrawlerToolLogin() {
        logger.info("开始初始化登陆页面");
        // 初始化全局的监听事件
        initListener();
        // 初始化窗体组件，并进行布局
        initComponents();
        // 设置窗体字体样式
        initStyle(inputPane);
        // 初始化注册监听
        registerListener();
        // 初始化窗体居中显示
        initPosition();

        CrawlerToolContextData.getInstance().setContextData(SystemConstants.CONTEXT_DATA_KEY_WEBSERVICE, WebServiceUtil.getInstance().getWsCtx().getBean("managerClient"));
        logger.info("结束初始化登陆页面");
    }

    /**
     * 窗体居中显示
     */
    private void initPosition() {
        // 取得屏幕大小
        Toolkit kit = Toolkit.getDefaultToolkit();
        Dimension oursize = getSize();
        Dimension screensize = kit.getScreenSize();
        // 窗口居中显示
        int x = (screensize.width - oursize.width) / 2;
        int y = (screensize.height - oursize.height) / 2;
        x = Math.max(0, x);
        y = Math.max(0, y);
        setLocation(x, y);
    }

    /**
     * 初始化全局Listener
     */
    private void initListener() {

        moveWindowListener = new MouseAdapter() {

            // 记录上次移动的位置
            private Point lastPoint;

            // 记住上一次的移动位置
            public void mousePressed(MouseEvent e) {
                lastPoint = e.getLocationOnScreen();
            }

            // 移动的时候设置新的窗体位置
            public void mouseDragged(MouseEvent e) {
                Point point = e.getLocationOnScreen();
                int offsetX = point.x - lastPoint.x;
                int offsetY = point.y - lastPoint.y;
                Rectangle bounds = getBounds();
                bounds.x += offsetX;
                bounds.y += offsetY;
                setBounds(bounds);
                lastPoint = point;
            }

            // 鼠标经过的时候触发
            public void mouseEntered(MouseEvent e) {
                if (e.getSource() == logoLabel)
                    logoLabel.setIcon(logoRoverIcon);
            }

            // 鼠标离开的时候触发
            public void mouseExited(MouseEvent e) {
                if (e.getSource() == logoLabel)
                    logoLabel.setIcon(logoIcon);
            }
        };

    }

    /**
     * 初始化组件
     */
    private void initComponents() {
        // 加载用户本地数据
        getPropertyValues();
        // 设置窗体名称
        setTitle("丑牛迷你采集器");
        // 设置系统任务栏的图标
        setIconImage(ImageManager.getImageByShortName("crawler_logo.png"));
        // 设置登陆图标
        buttonIcon = ImageManager.getImageIconByShortName("login_button.png");
        buttonRoverIcon = ImageManager.getImageIconByShortName("login_button_rover.png");
        buttonPressedIcon = ImageManager.getImageIconByShortName("login_button_pressed.png");
        // 设置logo图标
        logoIcon = ImageManager.getImageIconByShortName("login_logo.png");
        logoRoverIcon = ImageManager.getImageIconByShortName("login_logo_rover.png");
        // 创建logo的标签组件并绑定动态图标事件
        logoLabel = createDraggableLabel(logoIcon);
        // 登陆按钮组件
        btnLogin = new JButton();

        // 创建用户输入主体容器，并初始化控件布局
        inputPane = new JPanel() {
            private static final long serialVersionUID = 1L;
            private TexturePaint paint;
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                paint = createTexturePaint(ImageManager.getImageByShortName("login_background.png"));
                Graphics2D g2d = (Graphics2D) g;
                g2d.setPaint(paint);
                g2d.fillRect(0, 0, getWidth(), getHeight());
            }
        };
        // 窗体关闭方式 DISPOSE_ON_CLOSE
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        // 不显示边框和标题栏
        setUndecorated(true);
        // 使窗体透明化
        AWTUtilities.setWindowOpaque(this, false);
        // 设置窗体的大小
        setSize(width, height);

        // 设置登陆按钮的参数
        btnLogin.setBorder(null);
        btnLogin.setMargin(null);
        // 透明化
        btnLogin.setOpaque(false);
        // 设置图标
        btnLogin.setIcon(buttonIcon);
        // 需要翻转效果
        btnLogin.setRolloverEnabled(true);
        // 覆盖的时候的图标
        btnLogin.setRolloverIcon(buttonRoverIcon);
        // 按下的图标
        btnLogin.setPressedIcon(buttonPressedIcon);
        // 设置按钮透明
        btnLogin.setContentAreaFilled(false);
        // 设置不获取焦点
        btnLogin.setRequestFocusEnabled(false);

        // 顶部容器
        topPane = new JPanel(new BorderLayout());
        // 透明化
        logoLabel.setOpaque(false);
        // 透明化
        topPane.setOpaque(false);
        // 布局
        topPane.add(createDraggableLabel(ImageManager.getImageIconByShortName("login_left_top.png")), BorderLayout.WEST);
        topPane.add(logoLabel, BorderLayout.CENTER);
        topPane.add(createDraggableLabel(ImageManager.getImageIconByShortName("login_right_top.png")), BorderLayout.EAST);

        inputPane.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
        inputPane.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 5));
        inputPane.setPreferredSize(new Dimension(100, 30));
        // 用户名输入域的创建
        inputPane.add(createInputLabel("用户名:"));
        // 初始化用户登陆列表
        userNameTextField = new JFilterTextField(userIdList);
        userNameTextField.setText(lastUserId);
        userNameTextField.setPreferredSize(new Dimension(120, 26));
        inputPane.add(userNameTextField);

        // 密码输入域的创建
        inputPane.add(createInputLabel("密   码:"));
        passwordTextField = new JPasswordField("");
        passwordTextField.setPreferredSize(new Dimension(120, 26));
        inputPane.add(passwordTextField);

        // 语言选择域的创建
        inputPane.add(createInputLabel("语   言:"));
        JComboBox languageComboBox = new JComboBox(new String[] { "zh_CN" });
        languageComboBox.setPreferredSize(new Dimension(120, 26));
        inputPane.add(languageComboBox);

        inputPane.add(new JLabel());
        rememberMe = new JCheckBox("记住我");
        rememberMe.setOpaque(false);
        inputPane.add(rememberMe);

        netSetLabel = createInputLabel("网络设置");
        // 手型光标
        netSetLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
        inputPane.add(netSetLabel);

        JLabel regLabel = new UrlLabel("注册新账号", "http://www.kirk.com/register.html");
        JLabel forgetPasswordLabel = new UrlLabel("忘记密码", "http://www.kirk.com/member/forgot_password.html");
        exitLabel = createInputLabel("退出");
        // 手型光标
        exitLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 1));
        panel.setOpaque(false);
        panel.add(regLabel);
        panel.add(forgetPasswordLabel);
        panel.add(exitLabel);
        inputPane.add(panel);
        errorLabel = createInputLabel("");
        inputPane.add(errorLabel);

        // 创建一个边框布局模式的容器
        JPanel centerPane = new JPanel(new BorderLayout());
        // 设置容器透明化
        centerPane.setOpaque(false);
        setContentPane(centerPane);
        // 布局
        centerPane.add(btnLogin, BorderLayout.SOUTH);
        centerPane.add(createDraggableLabel(ImageManager.getImageIconByShortName("login_left.png")), BorderLayout.WEST);
        centerPane.add(inputPane, BorderLayout.CENTER);
        centerPane.add(createDraggableLabel(ImageManager.getImageIconByShortName("login_right.png")), BorderLayout.EAST);
        centerPane.add(topPane, BorderLayout.NORTH);
    }

    /**
     * 注册Listener
     */
    private void registerListener() {
        // 设置可拖动
        logoLabel.addMouseListener(moveWindowListener);
        logoLabel.addMouseMotionListener(moveWindowListener);
        topPane.addMouseListener(moveWindowListener);
        topPane.addMouseMotionListener(moveWindowListener);
        inputPane.addMouseListener(moveWindowListener);
        inputPane.addMouseMotionListener(moveWindowListener);
        // 登陆按钮设置监听
        btnLogin.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(login()){
                    setVisible(false);
                    JSplash.getInstance().splashOn();
                    JSplash.getInstance().increaseProgress(0, "丑牛正在初始化,请稍候...");
                    start();
                }
            }
        });
        netSetLabel.addMouseListener(new MouseAdapter(){
            public void mouseClicked(MouseEvent e) {
                //NetProxySettingDialog.getInstance().init(ui, Constant.OPTION_TYPE_ADD, "网络代理设置");
                //NetProxySettingDialog.getInstance().setVisible(true);
            }
        });
        exitLabel.addMouseListener(new MouseAdapter(){
            public void mouseClicked(MouseEvent e) {
                logger.info("退出软件，拜拜!!");
                dispose(); // 销毁
            }
        });
    }

    private void initStyle(JPanel panel){
        Component[] components = panel.getComponents();
        for(Component component : components){
            if(component instanceof JPanel){
                JPanel tempPanel = (JPanel)component;
                initStyle(tempPanel);
            }
            setupComponent(component);
        }
    }

    // 登陆逻辑的抽象方法
    public abstract boolean login();

    // 开始的抽象方法
    public abstract void start();

    private void setupComponent(Component c) {
        c.setFont(new Font("微软雅黑", 1, 14));
        c.setForeground(new Color(37, 81, 54));
    }

    /**
     * 取得属性文件中柜员号信息
     * <p>
     * 方法说明:
     * </p>
     * <li>获取当前用户配置文件中记录的已经成功登陆的柜员号并组装到userIdList中</li>
     * <li>获取当前用户配置文件中记录的最后一次成功登陆的柜员号并组装到lastUserId中</li>
     * <li>获取当前用户配置文件中记录的最后一次成功登陆的登录方式并组装到lastLoginMode中</li>
     */
    private void getPropertyValues() {
        if (logger.isInfoEnabled()) {
            logger.info("读取文件数据...");
        }
        String userIds = userCacheManager.getValue(UserConstants.FILE_PROPERTY_KEY_USER_IDS);
        userIdList = new ArrayList<Object>();
        if (StringUtils.isNotBlank(userIds)) {
            if (userIds.contains(",")) {
                for(String userId : userIds.split(",")) {
                    userIdList.add(userId);
                }
            } else {
                userIdList.add(userIds);
            }
        }
        lastUserId = userCacheManager.getValue(UserConstants.FILE_PROPERTY_KEY_LAST_USER_ID);
        if (logger.isInfoEnabled()) {
            logger.info("读取文件数据...完成");
        }
    }

    /**
     * 构建输入框label
     */
    private JLabel createInputLabel(String text) {
        JLabel label = new JLabel(text,JLabel.RIGHT);
        return label;
    }

    /**
     * 构建可拖动的label
     */
    private JLabel createDraggableLabel(ImageIcon icon) {
        JLabel label = new JLabel(icon);
        label.addMouseListener(moveWindowListener);
        label.addMouseMotionListener(moveWindowListener);
        return label;
    }

    public static TexturePaint createTexturePaint(Image image) {
        int imageWidth = image.getWidth(null);
        int imageHeight = image.getHeight(null);
        BufferedImage bi = new BufferedImage(imageWidth, imageHeight, 2);
        Graphics2D g2d = bi.createGraphics();
        g2d.drawImage(image, 0, 0, null);
        g2d.dispose();
        return new TexturePaint(bi, new Rectangle(0, 0, imageWidth, imageHeight));
    }

}
